package com.acme.controller;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.validation.groups.Default;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;
import com.acme.dao.ClaimDAO;
import com.acme.dao.UserDAO;
import com.acme.dao.security.DBUserDAO;
import com.acme.entity.Claim;
import com.acme.entity.Claim.HospitalInfoValidation;
import com.acme.entity.Claim.InjuryInfoValidation;
import com.acme.entity.Claim.UserValidation;
import com.acme.entity.User;
import com.acme.service.impl.ClaimForm;
import com.itextpdf.text.DocumentException;

@Transactional
@Controller
@SessionAttributes("claim")
public class ClaimCreationController{
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	@Autowired
	private JavaMailSender mailSender;
	
	@Autowired @Qualifier("claimEditedEmail")
	private SimpleMailMessage claimEditedEmail;
	
	@Autowired @Qualifier("claimCreatedEmail")
	private SimpleMailMessage claimCreatedEmail;
	
	@RequestMapping(value = "ClaimCreation", method = RequestMethod.GET)
	public ModelAndView claimCreation(final ModelMap modelMap){
		
		modelMap.addAttribute("claim", new Claim());
		
		Claim claim = new Claim();
		String username = SecurityContextHolder.getContext().getAuthentication().getName();
		User user = dbuserDAO.getUserByUsername(username);
		claim.setUser(user);
		
		return new ModelAndView("ClaimCreation", "claim", claim);
	}
	
	@RequestMapping(params = "_target0")
	public String processBeginning(final @ModelAttribute("claim") Claim claim ){

		return "ClaimCreation";
	}
	
	@RequestMapping(params = "_target1")
	public String processFirstStep(final @ModelAttribute("claim") Claim claim ){

		return "InjuryInfo";
	}
	
	@RequestMapping(params = "_target2")
	public String processSecondStep(final @ModelAttribute("claim") Claim claim ){

		if(!claim.isHospitalized()){
			logger.info("User NOT hospitalized - skipping Hospital Info");
			return "InjuryInfo";
		}
		return "HospitalInfo";
	}
	
	@RequestMapping(params = "_target3")
	public String processThirdStep(final @ModelAttribute("claim") Claim claim ){

		return "MedicareCoverageInfo";
	}
	
	@RequestMapping(params = "_target4")
	public String processFourthStep(final @ModelAttribute("claim") Claim claim ){

		return "PrivateCoverageInfo";
	}
	
	@RequestMapping(params = "_target5")
	public String processFifthStep(final @ModelAttribute("claim") Claim claim ){

		return "ClaimRegReview";
	}
	
	@RequestMapping(params = "_finalStep")
	public String submitClaim(final @ModelAttribute("claim") Claim claim, 
			final SessionStatus status ) throws MalformedURLException, DocumentException, IOException, ParseException {
		
//		if(claim.getUser().getfName().isEmpty())
//			claim.getUser().setfName("");
//		if(claim.getUser().getlName().isEmpty())
//			claim.getUser().setlName("");
//		if(claim.getUser().getInsuranceNumber().isEmpty())
//			claim.getUser().setInsuranceNumber("");
//		if(claim.getUser().getBirthday().isEmpty())
//			claim.getUser().setBirthday("");
//		if(claim.getUser().getGender().isEmpty())
//			claim.getUser().setGender("");
////		if(claim.isJobRelated()) // DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER
//		if(claim.getType().isEmpty())
//			claim.setType("");
		String myString3 = "May 15, 2010";
		Date myDate = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(myString3);

		User myUser2 = new User();
		myUser2.setfName(claim.getUser().getfName());
		myUser2.setlName(claim.getUser().getlName());
		myUser2.setInsuranceNumber("999-99-9999");
		myUser2.setGender("Male");
		myUser2.setBirthday(claim.getUser().getBirthday());
		myUser2.setGender(claim.getUser().getGender());
		
		Claim myClaim = new Claim(myUser2,"Injury",myDate.toString(),false,false,null,null,null,null,"Sprained ankle",false,"0",false,false,false,null,0,"Submitted",true);
		myClaim.setJobRelated(claim.isJobRelated());
		myClaim.setHospitalName(claim.getHospitalName());
		myClaim.setHospAdmitDate(claim.getHospAdmitDate());
		myClaim.setHospDischargeDate(claim.getHospDischargeDate());
		myClaim.setDiagnosis(claim.getDiagnosis());
		myClaim.setOtherInsCompName(claim.getOtherInsCompName());
		myClaim.setOtherInsCompID(claim.getOtherInsCompID());
		myClaim.setAdmittingPhysician(claim.getAdmittingPhysician());
		
		ClaimForm.createPDF(myClaim);

		status.setComplete();
		
		
		return "home"; 
		
	}

	@RequestMapping(params = "_next1")
	public String validateFirstStep(final @ModelAttribute("claim") @Validated({UserValidation.class}) Claim claim,
			BindingResult result){

		return validate(result, "ClaimCreation", "InjuryInfo");
	}
	
	@RequestMapping(params = "_next2")
	public String validateSecondStep(final @ModelAttribute("claim") @Validated({InjuryInfoValidation.class}) Claim claim,
			BindingResult result){

		if (result.hasErrors()){
			logger.info("Error found somewhere");
			return "InjuryInfo";
		}

		if(!claim.isHospitalized()){
			logger.info("NOT hospitalized");
			claim.setHospitalName("N/A");
			claim.setAdmittingPhysician("N/A");
			claim.setHospAdmitDate("N/A");
			claim.setHospDischargeDate("N/A");
			return "MedicareCoverageInfo";
		}

		logger.info("IS hospitalized");
		return "HospitalInfo";
	}
	
	@RequestMapping(params = "_next3")
	public String validateThirdStep(final @ModelAttribute("claim") @Validated({HospitalInfoValidation.class}) Claim claim,
			BindingResult result){

		return validate(result, "HospitalInfo", "MedicareCoverageInfo");

	}
	
	@RequestMapping(params = "_next4")
	public String validateFourthStep(final @ModelAttribute("claim") @Validated({HospitalInfoValidation.class}) Claim claim,
			BindingResult result){

		return validate(result, "MedicareCoverageInfo", "PrivateCoverageInfo");
	}
	
	@RequestMapping(params = "_next5")
	public String validateFifthStep(final @ModelAttribute("claim") @Validated({HospitalInfoValidation.class}) Claim claim,
			BindingResult result){

		return validate(result, "PrivateCoverageInfo", "ClaimRegReview");
	}
	
	@Autowired
	private UserDAO userDAO;
	@Autowired
	private DBUserDAO dbuserDAO;
	@Autowired
	private ClaimDAO claimDAO;

	
	@RequestMapping(params = "_nextFinal") //, value="ClaimRegReview", method = RequestMethod.POST
	public ModelAndView validateFinalStep(@ModelAttribute("claim") @Validated({Default.class}) Claim claim, //@ModelAttribute("claim") 
			BindingResult result, HttpServletRequest request) {
		// return a view which will be resolved by an excel view resolver

		
		//UserDetails userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
		ModelAndView mav = new ModelAndView();

			String username = SecurityContextHolder.getContext().getAuthentication().getName();
			User user = dbuserDAO.getUserByUsername(username);

			if(claim.getHospAdmitDate().isEmpty())
			claim.setHospAdmitDate("");
			if(claim.getHospDischargeDate().isEmpty())
			claim.setHospDischargeDate("");
			claim.setStatus("Submitted");
			claim.setUser(user);

			claimDAO.updateClaim(claim);
			claim = claimDAO.getClaimsByUser(user).get(0);
			sendClaimCreatedNotification(claim);
			request.getSession().setAttribute("claim", claim);
			String model =validate(result, "ClaimRegReview", "ViewCreatedClaim");
			mav = new ModelAndView(model);
			return  mav;
	
	}
	
	@RequestMapping(params = "_nextFinal", value="ViewClaim", method = RequestMethod.POST) //, value="ClaimRegReview", method = RequestMethod.POST
	public ModelAndView editClaimFinalStep(@ModelAttribute("claim") @Validated({Default.class}) Claim claim, //@ModelAttribute("claim") 
			BindingResult result, HttpServletRequest request) {
		// return a view which will be resolved by an excel view resolver

		
		//UserDetails userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
		ModelAndView mav = new ModelAndView();

			String username = SecurityContextHolder.getContext().getAuthentication().getName();
			User user = dbuserDAO.getUserByUsername(username);

			if(claim.getHospAdmitDate().isEmpty())
			claim.setHospAdmitDate("");
			if(claim.getHospDischargeDate().isEmpty())
			claim.setHospDischargeDate("");
			claim.setStatus("Submitted");
			claim.setUser(user);
			claimDAO.updateClaim(claim);
			sendClaimEditedNotification(claim);
			logger.info("email sent?");
			request.getSession().setAttribute("claim", claim);
			String model =validate(result, "ViewClaim", "ViewCreatedClaim");
			mav = new ModelAndView(model);
			return  mav;
	}
	
	@RequestMapping(value="ViewClaim", method = RequestMethod.POST)
	public ModelAndView editClaim(HttpServletRequest request) { 

		ModelAndView mav = new ModelAndView();

		int claimNum =  1;
		if (request.getParameter("editClaimBtn") != null) {
			claimNum = Integer.parseInt(request.getParameter("editClaimBtn"));
			request.getSession().setAttribute("claimNum", claimNum);
		} else if(request.getSession().getAttribute("claimNum") != null) {
			claimNum = (Integer) request.getSession().getAttribute("claimNum");
		}

		Claim claim = claimDAO.getClaimByID(claimNum);
		
		mav = new ModelAndView("ViewClaim", "claim", claim);

		return mav;
	}
	
	
	@RequestMapping(params = "_viewPDF")
	public ModelAndView downloadExcel(@ModelAttribute("claim") Claim claim){
		
		return new ModelAndView("pdfView", "listBooks", claim);
	}
	
	@RequestMapping(params = "_skip")
	public String skipToCompletedView(@ModelAttribute("claim") Claim claim){
		
		claim.getUser().setfName("Kyle");
		claim.getUser().setlName("Hightower");
		claim.getUser().setBirthday("1988-09-16");
		claim.getUser().setGender("Male");
		claim.getUser().setInsuranceNumber("1121212412121");
		
		return "ViewCreatedClaim";
	}
	private void attachClaimPDFAndSend(MimeMessageHelper helper, MimeMessage message, Claim claim) {
	
		try {
			ClaimForm.createPDF(claim); //creates file C:\ACMEClaim[ClaimID][UserLastName].pdf
		} catch (MalformedURLException e) {} catch (DocumentException e) {} catch (IOException e) {}
		
		String filename = "ACMEClaim" + claim.getClaimID() + claim.getUser().getlName();
		FileSystemResource file = new FileSystemResource("C:\\AcmeClaims\\" + filename + ".pdf");
		try {
			helper.addAttachment(file.getFilename(), file);
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		mailSender.send(message);
		Path path = FileSystems.getDefault().getPath("C:\\AcmeClaims\\", filename + ".pdf");
		try {
			Files.deleteIfExists(path);
		} catch (IOException e) {
			e.printStackTrace();
		} //deletes pdf file from C:\
	} 
	private void sendClaimCreatedNotification(Claim claim) {
		try {
			MimeMessage message = mailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			helper.setFrom(claimCreatedEmail.getFrom());
			helper.setTo(claim.getUser().getEmail());
			helper.setSubject(claimCreatedEmail.getSubject());
			String name = claim.getUser().getfName() + " " + claim.getUser().getlName();
			String claimNumber = Integer.toString(claim.getClaimID());
			helper.setText(String.format(claimCreatedEmail.getText(), name, claimNumber));
			attachClaimPDFAndSend(helper, message, claim);
		} catch(Exception e) {}
	}
	
	private void sendClaimEditedNotification(Claim claim) {
		try {
			MimeMessage message = mailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			helper.setFrom(claimEditedEmail.getFrom());
			helper.setTo(claim.getUser().getEmail());
			helper.setSubject(claimEditedEmail.getSubject());
			String name = claim.getUser().getfName() + " " + claim.getUser().getlName();
			String claimNumber = Integer.toString(claim.getClaimID());
			helper.setText(String.format(claimEditedEmail.getText(), name, claimNumber));
			attachClaimPDFAndSend(helper, message, claim);
		} catch(Exception e) {}
			
	}
	private String validate(BindingResult result, String errorResult, String successResult){
		if (result.hasErrors()) {
			return errorResult;
		}
		
		
		return successResult;
	}
	
}